package com.gxa.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.gxa.common.R;
import com.gxa.common.Status;
import com.gxa.common.vo.AppointmentPageRequest;
import com.gxa.common.vo.PatientVo;
import com.gxa.entity.SysReservation;
import com.gxa.entity.SysReservationSet;
import com.gxa.entity.SysUser;
import com.gxa.mapper.AppointmentManagementMapper;
import com.gxa.mapper.AppointmentSettingMapper;
import com.gxa.mapper.PatientManagementMapper;
import com.gxa.mapper.SysUserMapper;
import com.gxa.service.AppointmentManagementService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * @author MacieSerenity
 */
@Service
public class AppointmentManagementServiceImpl implements AppointmentManagementService {

    @Autowired
    AppointmentManagementMapper appointmentManagementMapper;
    @Autowired
    AppointmentSettingMapper appointmentSettingMapper;
    @Autowired
    SysUserMapper sysUserMapper;
    @Autowired
    PatientManagementMapper patientManagementMapper;


    final static Integer MAXIMUM_PAGE_SIZE = 50;
    final static Integer PAGE_NUM = 1;

    @Override
    public R findAllAppointment(AppointmentPageRequest appointmentPageRequest) {
        Integer pageSize = 20;
        Integer pageNum = 1;
        PageInfo<SysReservation> page = null;
        Integer total = 0;
        List<SysReservation> appointmentList = null;
        R result = new R();
        if (appointmentPageRequest != null) {
            //有这个查询对象就对查询条件进行验证，查看条件是否
            //查看页数和大小是否合格，如果没有这两个，或者其中一个为空则直接返回
            if (appointmentPageRequest.getPageNum() != null && appointmentPageRequest.getPageSize() != null) {
                if (appointmentPageRequest.getPageNum() < PAGE_NUM || appointmentPageRequest.getPageSize() > MAXIMUM_PAGE_SIZE) {
                    return R.failure(Status.BAD_PAGE_PARAM);
                }
                pageSize = appointmentPageRequest.getPageSize();
                pageNum = appointmentPageRequest.getPageNum();
            }
            //检查是否有查询条件
            if (appointmentPageRequest.getQuery() != null && !"".equals(appointmentPageRequest.getQuery())) {
                //有查询条件进行模糊查询
                appointmentList = findAllAppointmentByQuery(pageNum, pageSize, appointmentPageRequest.getQuery());
                total = appointmentManagementMapper.getQueryReservationCount(appointmentPageRequest.getQuery());
            } else {
                //没有查询条件，直接查询返回默认
                appointmentList = findAllAppointment(pageNum, pageSize);
                total = appointmentManagementMapper.getActiveReservationCount();
            }
        } else {
            //没有任何参数的查询
            appointmentList = findAllAppointment(pageNum, pageSize);
            total = appointmentManagementMapper.getActiveReservationCount();
        }
        page = new PageInfo<>(appointmentList);
        page.setTotal(total);
        result.fromStatus(Status.SUCCESS);
        result.setData(page);
        return result;
    }

    @Transactional(rollbackFor = {Exception.class})
    @Override
    public R addAppointmentById(Integer userID, Integer patientId, Integer days) {
        //要先判断用户和患者是否存在
        R result = validateUserAndPatient(userID, patientId);
        if (result.getCode() == 200) {
            //验证成功后 天数 必须不为空  而且要小于30天
            if (days != null && days < 30) {
                Integer daysByUserId = appointmentSettingMapper.getDaysByUserId(userID);
                if (daysByUserId == null) {
                    //表示没有找到这个预约医生，说明医生已经关闭预约或者已经删除预约，返回错误
                    return R.failure("没有该预约通道，或者该医生已经关闭了此次预约，请稍后再试");
                }
                //且小于医生设定的天数
                if (days > daysByUserId) {
                    return R.failure("超过了医生设定的最大天数，目前医生的最大预约天数是:" + daysByUserId);
                }
                //换算时间，转为string
                Date nowDate = new Date();
                Calendar calendar = Calendar.getInstance();
                calendar.setTime(nowDate);
                calendar.add(Calendar.DATE, days);
                SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
                String format = simpleDateFormat.format(calendar.getTime());
                //这里还需要判断那个医生的预约表人数是否超过限制，如果超过限制，那就不能插入，如果状态为不可预约，则也会报错
                Integer appointmentStatus = appointmentSettingMapper.getAppointmentStatusByUserId(userID);
                if (appointmentStatus == 0) {
                    //可预约，判断预约表人数是否超过
                    SysReservationSet appointmentByUserId = appointmentSettingMapper.getAppointmentByUserId(userID);
                    if (appointmentByUserId != null) {
                        //查询到数据，比对是否可以继续插入，否则返回错误
                        if (appointmentByUserId.getNowNumber() >= appointmentByUserId.getNumberLimit()) {
                            return R.failure("该负责人的预约已满，无法预约！");
                        } else {
                            try {
                                Integer nowNumber = appointmentByUserId.getNowNumber();
                                Date date =new Date();
                                appointmentSettingMapper.setAppointmentSettingNowNumberByUserId(userID, nowNumber + 1,date);
                                Integer integer = appointmentManagementMapper.insertReservation(userID, patientId, format);
                                if (integer == 0) {
                                    return R.failure("预约信息插入错误，请查看控制台");
                                } else {
                                    return R.ok();
                                }
                            } catch (Exception e) {
                                e.printStackTrace();
                                throw new RuntimeException("预约信息插入更新异常！详细信息：" + e.getMessage());
                            }
                        }
                    } else {
                        //没有查询到数据，没有这条预约信息，则直接返回错误
                        return R.failure("没有此预约信息！");
                    }
                } else {
                    //不可预约
                    return R.failure("错误！该医生状态为不可预约！");
                }
            } else {
                return R.failure("预约天数不能超过30天！");
            }
        } else {
            return result;
        }
    }

    /**
     * 根据ID处理，处理之后更改医生的nowNumber
     *
     * @param id 预约单的ID
     * @return
     */
    @Transactional(rollbackFor = {Exception.class})
    @Override
    public R handleAppointmentById(Integer id) {
        if (id != null) {
            Integer integerID = Integer.valueOf(id);
            //更改状态
            Integer result = appointmentManagementMapper.handleReservationById(integerID, new Date());
            //根据ID获取预约信息的负责人ID 也就是医生的ID
            SysReservation reservationById = appointmentManagementMapper.getReservationById(integerID);
//            根据医生的ID获取当前预约设置信息
            SysReservationSet appointmentByUserId = appointmentSettingMapper.getAppointmentByUserId(reservationById.getUserId());
//            预约设置中修改当前的人数
                appointmentSettingMapper.setAppointmentSettingNowNumberByUserId(appointmentByUserId.getUserId(), appointmentByUserId.getNowNumber() - 1, new Date());
            if (result != 0) {
                return R.ok();
            } else {
                return R.failure("在更改状态时发生错误，没有该条记录");
            }
        } else {
            return R.failure("ID获取失败！");
        }
    }

    @Transactional(rollbackFor = {Exception.class})
    @Override
    public R deleteAppointmentById(Integer id) {
        if (id != null) {
            try {
                //根据ID获取预约的负责人ID，
                Integer reservationUserIdById = appointmentManagementMapper.getReservationUserIdById(id);
                if (reservationUserIdById != null) {
                    //然后根据负责人ID去负责人设置表中查找数据，
                    //获取预约设置对象，不用判断是否删除，因为如果是删除的状态，也要获取信息进行用户数-1操作，如果设置只找到未删除的就会出现找不到的情况
                    SysReservationSet appointmentByUserId = appointmentSettingMapper.getAppointmentByUserId(reservationUserIdById);
                    Integer result = appointmentManagementMapper.deleteById(id, new Date());
                    //然后减一
                    //判断是否已处理，已处理就不用-1，若未处理，则需要-1
                    Integer statusById = appointmentManagementMapper.getStatusById(id);
                    if (statusById == 0) {
                        appointmentSettingMapper.setAppointmentSettingNowNumberByUserId(appointmentByUserId.getUserId(), appointmentByUserId.getNowNumber() - 1, new Date());
                    }
                    if (result != 0) {
                        return R.ok();
                    } else {
                        return R.failure("在删除时发生错误，没有该条记录");
                    }
                } else {
                    //是否要删除已经处理的
                    Integer noActiveStatusById = appointmentManagementMapper.getNoActiveStatusById(id);
                    if (noActiveStatusById != null) {
                        appointmentManagementMapper.forceDeleteNoActiveRecord(id);
                        return R.ok("删除成功");
                    } else {
                        return R.failure("没有找到关于这条记录的消息，该条信息可能已被处理，删除失败");
                    }
                }

            } catch (Exception e) {
                throw new RuntimeException("发生异常！具体信息：" + e.getMessage());
            }
        } else {
            return R.failure("ID获取失败！");
        }
    }

    /**
     * 判断用户和患者是否存在
     *
     * @param userId    用户ID
     * @param patientId 患者ID
     * @return 是否存在（both）
     */
    private R validateUserAndPatient(Integer userId, Integer patientId) {
        //是否有这个用户（负责人）
        SysUser userById = sysUserMapper.getActiveUserById(userId);
        if (userById == null) {
            return R.failure("没有这个负责人");
        } else {
            PatientVo patientVo = patientManagementMapper.selectActivePatientById(patientId);
            if (patientVo == null) {
                return R.failure("这个患者不存在！");
            } else {
                return R.ok();
            }
        }
    }


    /**
     * 查找所有的预约信息
     *
     * @return 查询到的信息列表
     */
    private List<SysReservation> findAllAppointment(Integer pageNum, Integer pageSize) {
        PageHelper.startPage(pageNum, pageSize);
        List<SysReservation> allSysReservation = appointmentManagementMapper.findAllSysReservation();
        return allSysReservation;
    }

    /**
     * 根据条件分页查询预约信息
     *
     * @param pageNum  页数
     * @param pageSize 分页大小
     * @param query    查询条件（名称/地址）
     * @return 查询到的信息列表
     */
    private List<SysReservation> findAllAppointmentByQuery(Integer pageNum, Integer pageSize, String query) {
        PageHelper.startPage(pageNum, pageSize);
        List<SysReservation> allSysReservationByQuery = appointmentManagementMapper.findAllSysReservationByQuery(query);
        return allSysReservationByQuery;
    }


}
